package com.pwrd.minispring.spring;

import com.pwrd.minispring.jdom.JDOM;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Auther syc.
 * @Date 2016/10/20 17:31.
 */
public class ClassPathXmlApplicationContext implements BeanFactory{

    Map<String, Object> beans = new HashMap<>();

    public ClassPathXmlApplicationContext(String xml) throws Exception {
        long lasting = System.currentTimeMillis();
        try {
            SAXBuilder builder = new SAXBuilder();
            Document doc = builder.build(JDOM.class.getClassLoader().getResourceAsStream(xml));
            Element root = doc.getRootElement();
            List allChildren = root.getChildren("bean");
            //add beans to bean factory from xml
            for (int i = 0; i < allChildren.size(); i++) {
                Element element = (Element) allChildren.get(i);
                String id = element.getAttributeValue("id");
                String clazz = element.getAttributeValue("class");
                System.out.println("id = " + id + "; clazz = " + clazz);
                Object o = Class.forName(clazz).newInstance();
                beans.put(id, o);
            }


            //inject the dependencies
            for (int i = 0; i < allChildren.size(); i++) {
                Element element = (Element) allChildren.get(i);
                Object o = beans.get(element.getAttributeValue("id"));

                for (Element property : (List<Element>)element.getChildren("property")) {
                    String name = property.getAttributeValue("name");
                    String bean = property.getAttributeValue("ref");
                    Object beanObject = beans.get(bean);

                    String method = "set" + name.substring(0,1).toUpperCase() + name.substring(1);
                    System.out.println("the method name is " + method);


                    Method m = o.getClass().getDeclaredMethod(method, beanObject.getClass().getInterfaces()[0]);

                    m.invoke(o, beanObject);

                }
            }

            System.out.println("运行时间：" + (System.currentTimeMillis() - lasting)
                    + "毫秒");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Object getBean(String beanName) {
        return beans.get(beanName);
    }
}
